#ifndef _WX_RENDERER_H_
#define _WX_RENDERER_H_

class wxDC;
class wxWindow;

#include "wx/gdicmn.h"
#include "wx/colour.h"
#include "wx/font.h"
#include "wx/bitmap.h"
#include "wx/string.h"


#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXGTK__)
#define wxHAS_NATIVE_RENDERER
#else
#undef wxHAS_NATIVE_RENDERER
#endif

enum {
  wxCONTROL_DISABLED   = 0x00000001,
  wxCONTROL_FOCUSED    = 0x00000002,
  wxCONTROL_PRESSED    = 0x00000004,
  wxCONTROL_SPECIAL    = 0x00000008,
  wxCONTROL_ISDEFAULT  = wxCONTROL_SPECIAL,
  wxCONTROL_ISSUBMENU  = wxCONTROL_SPECIAL,
  wxCONTROL_EXPANDED   = wxCONTROL_SPECIAL,
  wxCONTROL_SIZEGRIP   = wxCONTROL_SPECIAL,
  wxCONTROL_CURRENT    = 0x00000010,
  wxCONTROL_SELECTED   = 0x00000020,
  wxCONTROL_CHECKED    = 0x00000040,
  wxCONTROL_CHECKABLE  = 0x00000080,
  wxCONTROL_UNDETERMINED = wxCONTROL_CHECKABLE,

  wxCONTROL_FLAGS_MASK = 0x000000ff,



  wxCONTROL_DIRTY      = 0x80000000
};

struct wxSplitterRenderParams {

  wxSplitterRenderParams( wxCoord widthSash_, wxCoord border_, bool isSens_ )
    : widthSash( widthSash_ ), border( border_ ), isHotSensitive( isSens_ ) {
  }


  const wxCoord widthSash;


  const wxCoord border;


  const bool isHotSensitive;
};

struct wxHeaderButtonParams {
  wxHeaderButtonParams()
    : m_labelAlignment( wxALIGN_LEFT ) { }

  wxColour    m_arrowColour;
  wxColour    m_selectionColour;
  wxString    m_labelText;
  wxFont      m_labelFont;
  wxColour    m_labelColour;
  wxBitmap    m_labelBitmap;
  int         m_labelAlignment;
};

enum wxHeaderSortIconType {
  wxHDR_SORT_ICON_NONE,
  wxHDR_SORT_ICON_UP,
  wxHDR_SORT_ICON_DOWN
};

struct wxRendererVersion {
  wxRendererVersion( int version_, int age_ ) : version( version_ ), age( age_ ) { }
  enum {
    Current_Version = 1,
    Current_Age = 5
  };
  static bool IsCompatible( const wxRendererVersion& ver ) {
    return ver.version == Current_Version && ver.age >= Current_Age;
  }
  const int version;
  const int age;
};

class wxRendererNative {
  public:
    virtual int  DrawHeaderButton( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0,
                                   wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
                                   wxHeaderButtonParams* params = NULL ) = 0;
    virtual int  DrawHeaderButtonContents( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0,
                                           wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
                                           wxHeaderButtonParams* params = NULL ) = 0;
    virtual int GetHeaderButtonHeight( wxWindow *win ) = 0;
    virtual void DrawTreeItemButton( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) = 0;
    virtual void DrawSplitterBorder( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) = 0;
    virtual void DrawSplitterSash( wxWindow *win, wxDC& dc, const wxSize& size, wxCoord position, wxOrientation orient,
                                   int flags = 0 ) = 0;
    virtual void DrawComboBoxDropButton( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) = 0;
    virtual void DrawDropArrow( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) = 0;
    virtual void DrawCheckBox( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) = 0;
    virtual void DrawPushButton( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) = 0;
    virtual void DrawItemSelectionRect( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) = 0;
    virtual wxSplitterRenderParams GetSplitterParams( const wxWindow *win ) = 0;
    static wxRendererNative& Get();
    static wxRendererNative& GetGeneric();
    static wxRendererNative& GetDefault();

    #if wxUSE_DYNLIB_CLASS
    static wxRendererNative *Load( const wxString& name );
    #endif

    static wxRendererNative *Set( wxRendererNative *renderer );
    virtual wxRendererVersion GetVersion() const = 0;
    virtual ~wxRendererNative();
};

class wxDelegateRendererNative : public wxRendererNative {
  public:
    wxDelegateRendererNative()
      : m_rendererNative( GetGeneric() ) { }

    wxDelegateRendererNative( wxRendererNative& rendererNative )
      : m_rendererNative( rendererNative ) { }
    virtual int  DrawHeaderButton( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0,
                                   wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
                                   wxHeaderButtonParams* params = NULL ) {
      return m_rendererNative.DrawHeaderButton( win, dc, rect, flags, sortArrow, params );
    }

    virtual int  DrawHeaderButtonContents( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0,
                                           wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
                                           wxHeaderButtonParams* params = NULL ) {
      return m_rendererNative.DrawHeaderButtonContents( win, dc, rect, flags, sortArrow, params );
    }

    virtual int GetHeaderButtonHeight( wxWindow *win ) { return m_rendererNative.GetHeaderButtonHeight( win ); }

    virtual void DrawTreeItemButton( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) {
      m_rendererNative.DrawTreeItemButton( win, dc, rect, flags );
    }

    virtual void DrawSplitterBorder( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) {
      m_rendererNative.DrawSplitterBorder( win, dc, rect, flags );
    }

    virtual void DrawSplitterSash( wxWindow *win, wxDC& dc, const wxSize& size, wxCoord position, wxOrientation orient,
                                   int flags = 0 ) {
      m_rendererNative.DrawSplitterSash( win, dc, size, position, orient, flags );
    }
    virtual void DrawComboBoxDropButton( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) {
      m_rendererNative.DrawComboBoxDropButton( win, dc, rect, flags );
    }
    virtual void DrawDropArrow( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) {
      m_rendererNative.DrawDropArrow( win, dc, rect, flags );
    }
    virtual void DrawCheckBox( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) {
      m_rendererNative.DrawCheckBox( win, dc, rect, flags );
    }
    virtual void DrawPushButton( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) {
      m_rendererNative.DrawPushButton( win, dc, rect, flags );
    }
    virtual void DrawItemSelectionRect( wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ) {
      m_rendererNative.DrawItemSelectionRect( win, dc, rect, flags );
    }

    virtual wxSplitterRenderParams GetSplitterParams( const wxWindow *win ) {
      return m_rendererNative.GetSplitterParams( win );
    }
    virtual wxRendererVersion GetVersion() const { return m_rendererNative.GetVersion(); }

  protected:
    wxRendererNative& m_rendererNative;

    DECLARE_NO_COPY_CLASS( wxDelegateRendererNative )
};

#ifndef wxHAS_NATIVE_RENDERER


inline wxRendererNative& wxRendererNative::GetDefault() {
  return GetGeneric();
}

#endif

void wxRenderer_DrawChoice( wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0 );
void wxRenderer_DrawComboBox( wxWindow* win, wxDC& dc,const wxRect& rect, int flags = 0 );
void wxRenderer_DrawTextCtrl( wxWindow* win, wxDC& dc,const wxRect& rect, int flags = 0 );
void wxRenderer_DrawRadioButton( wxWindow* win, wxDC& dc,const wxRect& rect, int flags = 0 );

#endif
